package dynamic.mybatisplus.core.toolkit;

import com.baomidou.mybatisplus.annotation.IdType;

import com.baomidou.mybatisplus.core.handlers.AnnotationHandler;

import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import dynamic.ibatis.session.DConfiguration;
import dynamic.ibatis.session.SqlSessionFactory;
import dynamic.injector.DISqlInjector;
import dynamic.metadata.DTableInfo;
import dynamic.metadata.DTableInfoHelper;
import dynamic.metadata.EntityClass;
import dynamic.mybatisplus.core.config.DGlobalConfig;
import dynamic.mybatisplus.core.handlers.MetaObjectHandler;


import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class DGlobalConfigUtils {

    /**
     * 缓存全局信息
     */
    private static final Map<String, DGlobalConfig> GLOBAL_CONFIG = new ConcurrentHashMap<>();

    /**
     * 获取当前的SqlSessionFactory
     *
     * @param clazz 实体类
     * @deprecated 3.5.3.2 尽量少用,后期取消此方法获取实例
     */
    @Deprecated
    public static SqlSessionFactory currentSessionFactory(EntityClass clazz) {
        Assert.notNull(clazz, "Class must not be null");
        DTableInfo tableInfo = DTableInfoHelper.getTableInfo(clazz);
        Assert.notNull(tableInfo, ClassUtils.getUserClass(clazz).getName() + " Not Found TableInfoCache.");
        return getGlobalConfig(tableInfo.getConfiguration()).getSqlSessionFactory();
    }

    /**
     * 获取默认 MybatisGlobalConfig
     */
    public static DGlobalConfig defaults() {
        return new DGlobalConfig().setDbConfig(new DGlobalConfig.DbConfig());
    }

    /**
     * <p>
     * 设置全局设置(以configuration地址值作为Key)
     * <p/>
     *
     * @param configuration Mybatis 容器配置对象
     * @param globalConfig  全局配置
     */
    public static void setGlobalConfig(DConfiguration configuration, DGlobalConfig globalConfig) {
        Assert.isTrue(configuration != null && globalConfig != null, "Error: Could not setGlobalConfig");
        // 设置全局设置
        GLOBAL_CONFIG.putIfAbsent(Integer.toHexString(configuration.hashCode()), globalConfig);
    }

    /**
     * 获取MybatisGlobalConfig (统一所有入口)
     *
     * @param configuration Mybatis 容器配置对象
     */
    public static DGlobalConfig getGlobalConfig(DConfiguration configuration) {
        Assert.notNull(configuration, "Error: You need Initialize MybatisConfiguration !");
        final String key = Integer.toHexString(configuration.hashCode());
        return CollectionUtils.computeIfAbsent(GLOBAL_CONFIG, key, k -> defaults());
    }

    public static List<IKeyGenerator> getKeyGenerators(DConfiguration configuration) {
        return getGlobalConfig(configuration).getDbConfig().getKeyGenerators();
    }

    public static IdType getIdType(DConfiguration configuration) {
        return getGlobalConfig(configuration).getDbConfig().getIdType();
    }

    public static DGlobalConfig.DbConfig getDbConfig(DConfiguration configuration) {
        return getGlobalConfig(configuration).getDbConfig();
    }

    public static DISqlInjector getSqlInjector(DConfiguration configuration) {
        return getGlobalConfig(configuration).getSqlInjector();
    }

    public static Optional<MetaObjectHandler> getMetaObjectHandler(DConfiguration configuration) {
        return Optional.ofNullable(getGlobalConfig(configuration).getMetaObjectHandler());
    }

    public static Optional<AnnotationHandler> getAnnotationHandler(DConfiguration configuration) {
        return Optional.ofNullable(getGlobalConfig(configuration).getAnnotationHandler());
    }

    public static Class<?> getSuperMapperClass(DConfiguration configuration) {
        return getGlobalConfig(configuration).getSuperMapperClass();
    }

    public static boolean isSupperMapperChildren(DConfiguration configuration, Class<?> mapperClass) {
        return getSuperMapperClass(configuration).isAssignableFrom(mapperClass);
    }

    public static Map<String,Set<EntityClass>> getMapperRegistryCache(DConfiguration configuration) {
        return getGlobalConfig(configuration).getMapperRegistryCache();
    }
}
